﻿#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
/*
[i--j-- i--j-  i--j  i--j+ i--j++]
[i-j--  i-j-   i-j   i-j+  i-j++ ]
[ij--   ij-    ij    ij+   ij++  ]
[i+j--  i+j-   i+j   i+j+  i+j++ ]
[i++j-- i++j-  i++j  i++j+ i++j++]

[00 01 02 03] 
[10 11 12 13]
[20 21 22 23]
[30 31 32 33]
Mép trên i=0	mép trái j=0	mép dưới i=n-1	mép phải j=n-1
góc trên trái 00	góc dưới trái n-10	góc trên phai 0n-1	góc dưới phải n-1n-1
*/
#define MAX 100

struct ToaDo{
	int x,y;
};
#pragma region Khai báo hàm

void ghifile(char *fname, int a[MAX][MAX], int cap); 
void docFile(char fname[],int a[MAX][MAX], int &cap); 
void inMatran(int a[MAX][MAX], int cap);
int KiemTraHopLe(int a[MAX][MAX],int cap, int &Luot);// Kiểm tra xem file load lên có hợp lệ không và xác định lượt đi của ai
ToaDo danhCo(int a[MAX][MAX], int cap, int Luot);
int KiemTraThangThua(int a[MAX][MAX], int cap, ToaDo tdo, int Luot);
int KiemTraXien1(int a[MAX][MAX], int cap, ToaDo tdo, int Luot);
int KiemTraXien2(int a[MAX][MAX], int cap, ToaDo tdo, int Luot);
int	KiemTraNgang(int a[MAX][MAX], int cap, ToaDo tdo, int Luot);
int KiemTraDoc(int a[MAX][MAX], int cap, ToaDo tdo, int Luot);

#pragma endregion

int main(){
	int a[MAX][MAX];
	int cap; // cấp ma trân ( sân chơi)
	int Luot; // luot di cua 0 la 0, luot di cua 1 la 1

	ghifile("output.txt",a,15);// hàm này tạo ra sân chơi rổng - tất cả các giá trị = -1, có thể load file ma trân khác lên để kiểm tra và chơi tiếp
	// cấu trúc file nhập vào: dòng đầu chứa một giá trị là kích thước ma trận vuông, các dòng tiếp theo chứa (-1, 1, 0);
	docFile("output.txt",a,cap); 
	inMatran(a,cap);	
	int kq;	
	char q; // Biến kiểm tra: chơi tiếp hay quit

#pragma region Kiểm tra xem file load lên có hợp lệ không và xác định lượt đi của ai

	if (KiemTraHopLe(a,cap,Luot)==-1){ // kiem tra file input hop le ko
		cout<<"\nKhong Hop le!"<<endl;
		getch();// Không hợp lệ thì out
		return 0;
	}
	// còn hợp lệ thì chạy tiến đoạn dưới
#pragma endregion
#pragma region Kiểm tra xem có ai thắng khi vừa load file lên không

	ToaDo td;
	for (int i = 0; i < cap; i++){
		for (int j = 0; j < cap; j++){
			//cout<<i<<j<<endl;
			td.x=i;td.y=j;
			kq=KiemTraThangThua(a,cap,td,Luot);		

			if (kq==1 || kq==0){
				cout<<"            ***********************"<<endl;
				cout<<"            *Congratulation! "<<kq<<" won*"<<endl;
				cout<<"            ***********************"<<endl;
				// Khi có người chiến thắng ngay khi load file lên hỏi người chơi muốn chơi tiến không
				cout<<"\n\nEnter: q for quit or any other key to play again!"<<endl;
				cin>>q;
				if (q=='q' || q=='Q') return 1;
				system("cls");
				ghifile("output.txt",a,15); // in ma trận rổng chơi lại từ đầu
				docFile("output.txt",a,cap);// đọc ma trận rổng lên		
				inMatran(a,cap);	// in ra
				Luot=0; // cho 0 di trước
			}
		}	
	}	

#pragma endregion
#pragma region Đánh cờ

	ToaDo tdo;			
	for(;;){
		do{		// file input hop le gio la choi			
			tdo= danhCo(a,cap,Luot);
			system("cls");
			inMatran(a,cap);			
			kq=KiemTraThangThua(a,cap,tdo,Luot);
			//doi luot
			if (Luot==0)
			{
				Luot=1;
			}else Luot=0;
		}while(kq==-1);
		if (kq==1 || kq==0)
		{
			cout<<"            ***********************"<<endl;
			cout<<"            *Congratulation! "<<kq<<" won*"<<endl;
			cout<<"            ***********************"<<endl;
		}	
		cout<<"\n\nEnter: q for quit or any other key to play again!"<<endl;
		cin>>q;
		if (q=='q' || q=='Q') return 1;
		system("cls");
		//ghifile("output.txt",a,15); // in ma trận rổng chơi lại từ đầu
		docFile("output.txt",a,cap);// đọc ma trận rổng lên		
		inMatran(a,cap);	// in ra
		Luot=0; // cho 0 di trước
	}

#pragma endregion

	getch();
	return 0;
}
int	KiemTraXien2(int a[MAX][MAX], int cap, ToaDo tdo, int Luot){	
	int dem=1;
	int x= tdo.x, x1= tdo.x;
	int y= tdo.y, y1= tdo.y;
	// gốc phải trên đi chéo xuống
	if (x+1<cap && y-1<cap){					
		while (a[x+1][y-1]==a[x][y]){
			dem++;					
			if (dem==5) return a[x][y];
			x++;								
			y--;
		}
	}
	// phai
	if (tdo.x-1>=0 && tdo.y+1>=0){						
		while (a[x1-1][y1+1]==a[x1][y1]){
			dem++;					
			if (dem==5) return a[x1][y1];
			x1--;	
			y1++;
		}			
	}
	return -1;
}
int	KiemTraXien1(int a[MAX][MAX], int cap, ToaDo tdo, int Luot){	
	int dem=1;
	int x= tdo.x, x1= tdo.x;
	int y= tdo.y, y1= tdo.y;
	// gốc trái trên đi chéo xuống
	if (x+1<cap && y+1<cap){					
		while (a[x+1][y+1]==a[x][y]){
			dem++;					
			if (dem==5) return a[x][y];
			x++;								
			y++;
		}
	}
	// phai
	if (tdo.x-1>=0 && tdo.y-1>=0){						
		while (a[x1-1][y1-1]==a[x1][y1]){
			dem++;					
			if (dem==5) return a[x1][y1];
			x1--;	
			y1--;
		}			
	}
	return -1;
}
int	KiemTraDoc(int a[MAX][MAX], int cap, ToaDo tdo, int Luot){	
	int dem=1;
	int x= tdo.x, x1= tdo.x;
	int y= tdo.y, y1= tdo.y;
	// di xuống
	if (x+1<cap){					
		while (a[x+1][y]==a[x][y]){
			dem++;					
			if (dem==5) return a[x][y];
			x++;												
		}
	}
	// phai
	if (tdo.x-1>=0){						
		while (a[x1-1][y1]==a[x1][y1]){
			dem++;					
			if (dem==5) return a[x1][y1];
			x1--;	
		}			
	}
	return -1;
}
int	KiemTraNgang(int a[MAX][MAX], int cap, ToaDo tdo, int Luot){	
	int dem=1;
	int x= tdo.x, x1= tdo.x;
	int y= tdo.y, y1= tdo.y;
	// trai
	if (y+1<cap){					
		while (a[x][y+1]==a[x][y]){
			dem++;					
			if (dem==5) return a[x][y];
			y++;												
		}
	}
	// phai
	if (tdo.y-1>=0){						
		while (a[x1][y1-1]==a[x1][y1]){
			dem++;					
			if (dem==5) return a[x1][y1];
			y1--;	
		}			
	}
	return -1;
}
int KiemTraThangThua(int a[MAX][MAX], int cap, ToaDo tdo, int Luot){	
	int kq;
	kq = KiemTraNgang(a,cap,tdo,Luot);	
	if (kq!=-1) return kq;

	kq = KiemTraDoc(a,cap,tdo,Luot);
	if (kq!=-1) return kq;

	kq = KiemTraXien1(a,cap,tdo,Luot);
	if (kq!=-1) return kq;

	kq = KiemTraXien2(a,cap,tdo,Luot);
	if (kq!=-1) return kq;

	return -1;
}
ToaDo danhCo(int a[MAX][MAX], int cap, int Luot){	
	ToaDo tdo;
	if (Luot==0) // luot di cua 0
	{				
		cout<<"Luot di 0: (hang, cot) = ";
		cin>>tdo.x;
		cin>>tdo.y;
		while (a[tdo.x][tdo.y] != -1)
		{
			cout<<"\nVi tri nay da danh roi, chon lai (hang, cot) = ";
			cin>>tdo.x;
			cin>>tdo.y;
		}
		a[tdo.x][tdo.y] = 0;	// gán giá trị là 0 ứng với lượt người choi 0 tại vị trí đánh	
	}else { // Luot di cua 1(x)
		cout<<"Luot di X: (hang, cot) = ";
		cin>>tdo.x;
		cin>>tdo.y;		
		while (a[tdo.x][tdo.y] != -1) // Trong khi vị trí nhập vào đã đánh rồi(1, 0) khác (-1) thì nhập lại
		{
			cout<<"\nVi tri nay da danh roi, chon lai (hang, cot) = ";
			cin>>tdo.x;
			cin>>tdo.y;
		}
		a[tdo.x][tdo.y] = 1;	// gán giá trị là 1 ứng với lượt người choi 1 tại vị trí đánh	
	}
	return tdo;// trả về tọa độ người chơi đã đánh thành công để cho các sử lý khác dùng
}
int KiemTraHopLe(int a[MAX][MAX],int cap, int &Luot){ // kiểm tra ma trận nhập hợp lệ không.
	int dem0=0, dem1=0, kq;

	for (int i = 0; i < cap; i++){
		for (int j = 0; j < cap; j++){
			if (a[i][j]==1) dem1++; // tính tổng quân cờ 1
			if (a[i][j]==0) dem0++; // tính tổng quân cờ 0
		}
	}// rồi đem so sánh (số quân cờ 2 bên chênh lệch nhau [0-1]	--> kết luận có hợp lệ không
	if (dem0-dem1==1) return Luot=1;// hợp lệ lượt đánh tiến theo là người choi 1
	else if (dem1-dem0==1) return Luot=0;// hợp lệ lượt đánh tiến theo là người choi 0
	else if(dem0==dem1) return Luot=0;// nếu quân số 0 1 bằng nhau thì nhường cho 0 đánh trước
	return -1;// Không hợp lệ
}
void inMatran(int a[MAX][MAX], int cap){	
	cout<<"\n\n"<<endl;
	cout<<"  ";
	for (int i = 0; i < cap; i++) printf("%3d",i); // in thước đo ngang
	cout<<endl;
	for (int i=0; i<cap; i++){
		printf("%2d",i);// in thước đo dọc và ma trận từ file
		for(int j=0; j<cap; j++){
			if (a[i][j]==-1)		printf("  .");// nếu giá trị = -1( rổng) thì in (  .)
			else if (a[i][j]==1)	printf("  X");// nếu quân cờ 1 thì in X
			else					printf("%3d",a[i][j]); // nếu quân cờ 0 thì in bình thường
		}
		cout<<"\n"<<endl;
	}
}
void ghifile(char *fname, int a[MAX][MAX], int cap)
{ 
	FILE *fp; 
	fp = fopen(fname,"wt"); 
	//sv2010 
	// fopen_s(&fp,fname,"wt"); 
	if(!fp) return; 

	fprintf(fp,"%d\n",cap);
	for (int i = 0; i < cap; i++){
		for (int j = 0; j < cap; j++){
			a[i][j]=-1;
			fprintf(fp,"%d ",a[i][j]); 
		}
		fprintf(fp,"\n");
	}
	fclose(fp); 
} 
void docFile(char fname[],int a[MAX][MAX], int &cap)
{ 
	FILE *fp; 
	fp = fopen(fname,"rt"); 
	//sv2010 
	// fopen_s(&fp,fname,"wt"); 
	if(!fp) return; 
	char temp[100]; 
	fscanf(fp,"%d",&cap);
	for (int i=0; i<cap; i++){
		for (int j = 0; j < cap; j++){
			//fgets(temp,2,fp);//doc kyd tu xuong dong cua lenh scanf 
			//fgets(temp,100,fp);			
			fscanf(fp,"%d", &a[i][j]); 
		}
	}
	fclose(fp); 
}	